// 检验是否是手机号
export function isMobile(mobile) {
   if (!mobile) return
   return mobile.toString().length === 11
}

// 重写toFixed()方法,原本的toFixed()方法是四舍六入
/* eslint-disable */
Number.prototype.toFixed = function(d) {
   let s = this + ''
   if (!d) d = 0
   if (s.indexOf('.')=== -1) s += '.'
   s += new Array(d + 1).join('0')
   if (new RegExp('^(-|\\+)?(\\d+(\\.\\d{0,' + (d + 1) + '})?)\\d*$').test(s)) {
      let s = '0' + RegExp.$2
      let pm = RegExp.$1
      let a = RegExp.$3.length
      let b = true
      if (a===d + 2) {
         a = s.match(/\d/g)
         if (parseInt(a[a.length - 1]) > 4) {
            for (let i = a.length - 2; i >= 0; i--) {
               a[i] = parseInt(a[i]) + 1
               if (a[i]==='10') {
                  a[i] = '0'
                  b = i!==1
               } else {
                  break
               }
            }
         }
         s = a
         .join('')
         .replace(new RegExp('(\\d+)(\\d{' + d + '})\\d$'), '$1.$2')
      }
      if (b) s = s.substr(1)
      return (pm + s).replace(/\.$/, '')
   }
   return this + ''
}

/**
 * 金额格式化
 * 每三位一个逗号
 * @param {number} num 需格式化的金额
 * @param {number} len 保留小数位数
 * @returns {string}
 */
export function formatMoney(num, len = 2) {
   try {
      //这里的toFixed()方法已经重写
      return Number(num)
      .toFixed(len)
      .replace(/\B(?=(\d{3})+(\D|$))/g, ',')
   } catch (err) {
      return '-'
   }
}

/**
 * 时间戳转时间
 * @param date    123333333333
 * @returns {string|*}  1973-11-28 19:15:33
 */
export const formatDate = function(date) {
   if (!date) return

   date = new Date(date)
   let Y = date.getFullYear() + '-'
   let M =
      (date.getMonth() + 1 < 10
         ? '0' + (date.getMonth() + 1)
         :date.getMonth() + 1) + '-'
   let D = (date.getDate() < 10 ? '0' + date.getDate():date.getDate()) + ' '
   let h =
      (date.getHours() < 10 ? '0' + date.getHours():date.getHours()) + ':'
   let m =
      (date.getMinutes() < 10 ? '0' + date.getMinutes():date.getMinutes()) +
      ':'
   let s = date.getSeconds() < 10 ? '0' + date.getSeconds():date.getSeconds()
   return Y + M + D + h + m + s
}

/**
 * 树深度搜索，类比数组的filter方法
 * @param { treeData } treeData
 * @param {callback} callback 返回值为真时当前的treeNode会被添加到filters数组中
 * @returns { Array<TreeNode> } 搜索结果 一组包含满足条件的所有树节点的数组
 */
export function treeDeepSearch(treeData, callback) {
   let filters = []

   function search(tree, fn) {
      for (let i = 0; i < tree.length; i++) {
         if (tree[i].children && tree[i].children.length > 0) {
            fn(tree[i]) && filters.push(tree[i])
            search(tree[i].children, fn)
         } else {
            fn(tree[i]) && filters.push(tree[i])
         }
      }
   }

   search(treeData, callback)
   return filters
}

/**
 * 防抖
 * 在指定的时间内只执行一次回调函数，若在指定时间内又触发了该事件，则会基于此刻重新计算回调函数的执行时间
 * @param fn
 * @param delay
 * @returns {Function}
 */
export function debounce(fn, delay) {
   let timer = null
   return function() {
      let context = this,
         args = arguments
      timer && clearTimeout(timer)
      timer = setTimeout(() => {
         fn.apply(context, args)
      }, delay)
   }
}

/**
 * 节流
 * 预先设定一个执行周期，只有触发事件间隔大于等于这个执行周期，才会执行回调函数
 * @param fn
 * @param delay
 * @returns {Function}
 */
export function throttle(fn, delay) {
   let start = 0,
      timer = null
   return function() {
      let context = this,
         args = arguments,
         now = new Date()

      //计算剩余时间
      let remaining = delay - (now - start)

      //如果时间间隔超出了我们设定的时间间隔阈值，那就不等了，无论如何要反馈给用户一次响应
      if (remaining <= 0) {
         timer && clearTimeout(timer)
         timer = null
         fn.apply(context, args)
         start = now
      } else {
         //如果时间间隔小于我们设定的时间间隔阈值，则为本次触发操作设立一个新的定时器
         timer = setTimeout(() => {
            fn.apply(context, args)
         }, delay)
      }
   }
}

/**
 * 延时指定的时间
 * @param delay
 */
export function sleep(delay) {
   for (let t = Date.now(); Date.now() - t <= delay;) {
   }
}

/**
 * 快速格式化get请求参数
 * @param obj
 * @returns {string}
 */
export function buildParams(obj) {
   const params = []
   Object.keys(obj).forEach((key) => {
      let value = obj[key]
      // 如果值为undefined我们将其置空
      if (typeof value==='undefined' || value==='') {
         return
      }
      // 对于需要编码的文本（比如说中文）我们要进行编码
      params.push([key, encodeURIComponent(value)].join('='))
   })

   return params.join('&')
}

// 重复字符串str n次
export function repeat(str, n) {
   let res = ''
   while (n) {
      if (n % 2===1) {
         res += str
      }
      if (n > 1) {
         str += str
      }
      n >>= 1
   }
   return res
}

/**
 * 字符串脱敏
 * @param {string} str 原字符串
 * @param {number} starOffset 前保留位数
 * @param {number} endOffset 后保留位数
 * 15178831130 -> 151****1138
 */
export function stringMosaic(str, starOffset, endOffset) {
   if (!str) return ''
   str = String(str)
   const mosaic = repeat('*', str.length - starOffset - endOffset)
   const express = new RegExp(`^(.{${starOffset}}).*(.{${endOffset}})$`)
   return str.replace(express, (o, $1, $2) => {
      return `${$1}${mosaic}${$2}`
   })
}

/**
 * 计算两个月份之间的差值 d2-d1
 * @param d1 new Date(2019, 7)
 * @param d2 new Date(2018, 2)
 * @returns {number}
 */
export function monthDiff(d1, d2) {
   let months
   months = (d2.getFullYear() - d1.getFullYear()) * 12
   months -= d1.getMonth()
   months += d2.getMonth()
   return months
}
